package se.energimyndigheten.lampguiden;

import android.content.Context;
import android.content.res.Configuration;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBarActivity;
import android.support.v7.app.ActionBarDrawerToggle;
import android.support.v7.widget.Toolbar;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.CheckedTextView;
import android.widget.ListView;

import se.energimyndigheten.lampguiden.bulbreplacement.SocketGridFragment;
import se.energimyndigheten.lampguiden.conversiontable.ConversionFragment;
import se.energimyndigheten.lampguiden.info.InfoListFragment;
import se.energimyndigheten.lampguiden.lighting.LightingListFragment;

public class MainActivity extends ActionBarActivity implements XmlClickable, FragmentSwapper, FragmentManager.OnBackStackChangedListener {

    public static final String HTML_BASEPATH = "file:///android_asset/submodule_html/";
    public static final int ACTIVITY_SOCKET = 0;
    public static final int ACTIVITY_LIGHTING = 1;
    public static final int ACTIVITY_CONVERSION = 2;
    public static final int ACTIVITY_INFO = 3;

    private static final String TAG = MainActivity.class.getSimpleName();
    private static final String FRAG_TAG = "ACTIVE_FRAG";
    private static final String STATE_ACTIVE = "ACTIVE_FRAG";
    private static final int[] DRAWER_ICONS = new int[]{R.drawable.ic_navi_socket, R.drawable.ic_navi_lighting, R.drawable.ic_navi_conversion, R.drawable.ic_navi_info};
    private static final int[] DRAWER_ICONS_SELECTED = new int[]{R.drawable.ic_navi_socket_active, R.drawable.ic_navi_lighting_active, R.drawable.ic_navi_conversion_active, R.drawable.ic_navi_info_active};
    private static final Integer[] DRAWER_TITLES = new Integer[]{R.string.section_socket_title, R.string.section_lighting_title, R.string.section_conversion_title, R.string.section_info_title};
    private static final int[] FRAGMENT_TITLES = new int[] {R.string.section_socket_hint,  R.string.section_lighting_title, R.string.section_conversion_title, R.string.section_info_title};

    private DrawerLayout mDrawerLayout;
    private ActionBarDrawerToggle mDrawerToggle;
    private CharSequence mTitle;
    private CharSequence mDrawerTitle;
    private ListView mDrawerList;
    private View mDrawer;
    private CheckedTextView mActiveDrawerItem = null;
    private int mActivePosition = 0;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.navigation_drawer);

        // navigation drawer
        mActivePosition = 0;
        mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
        mDrawerList = (ListView) findViewById(R.id.navigation_drawer);
        mDrawer = findViewById(R.id.drawer);

        mTitle = mDrawerTitle = getTitle();
        mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout, R.string.open_menu, R.string.close_menu) {

            public void onDrawerClosed(View view) {
                super.onDrawerClosed(view);
                getSupportActionBar().setTitle(mTitle);
                invalidateOptionsMenu();
            }

            public void onDrawerOpened(View drawerView) {
                super.onDrawerOpened(drawerView);
                getSupportActionBar().setTitle(mDrawerTitle);
                invalidateOptionsMenu();
            }
        };
        mDrawerLayout.setDrawerListener(mDrawerToggle);

        // tool bar
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
        getSupportActionBar().setDisplayHomeAsUpEnabled(true);
        getSupportActionBar().setHomeButtonEnabled(true);

        // listen to back stack changes to know active fragments and toggle tool bar menu
        getSupportFragmentManager().addOnBackStackChangedListener(this);

        mDrawerList.setAdapter(new DrawerAdapter(this));
        mDrawerList.setOnItemClickListener(new DrawerItemClickListener());
        mDrawerList.setItemChecked(mActivePosition, true);
        FragmentManager fragmentManager = getSupportFragmentManager();
        fragmentManager.beginTransaction().add(R.id.content_frame, new SocketGridFragment(), FRAG_TAG).commit();
    }

    @Override
    public void onPostCreate(Bundle savedInstanceState) {
        super.onPostCreate(savedInstanceState);
        mDrawerLayout.openDrawer(mDrawer);
        mDrawerToggle.syncState();
    }

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
    }

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        // remember which menu item was active
        outState.putInt(STATE_ACTIVE, mActivePosition);
        super.onSaveInstanceState(outState);
    }

    @Override
    protected void onRestoreInstanceState(Bundle state) {
    }

    @Override
    public boolean onPrepareOptionsMenu(Menu menu) {
        // option menu has changed
        handleDisplayHomeUp();
        return super.onPrepareOptionsMenu(menu);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Log.v(TAG, "onOptionsItemsSelected");
        if (mDrawerToggle.isDrawerIndicatorEnabled() && mDrawerToggle.onOptionsItemSelected(item)) {
            return true;
        }

        switch (item.getItemId()) {
            case android.R.id.home:
                // home was pressed
                // pop backstack and show icon for navigation drawer
                getSupportFragmentManager().popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
                mDrawerToggle.setDrawerIndicatorEnabled(true);
                getSupportActionBar().setDisplayShowHomeEnabled(false);
                break;
            case R.id.menu_info:
                // info button was pressed
                // get info parameters from active fragment
                Fragment theFrag = getSupportFragmentManager().findFragmentByTag(FRAG_TAG);
                if (theFrag instanceof HasInfoPage) {
                    Fragment infoFragment = new InfoFragment();
                    Bundle args = new Bundle();
                    args.putString(InfoFragment.EXTRA_HTML_PATH, HTML_BASEPATH + ((HasInfoPage) theFrag).getInfoPageUrl());
                    args.putString(InfoFragment.EXTRA_TITLE, ((HasInfoPage) theFrag).getInfoPageTitle());
                    infoFragment.setArguments(args);
                    swapFragment(infoFragment, true);
                }
                break;
        }
        return super.onOptionsItemSelected(item);
    }

    @Override
    public void onBackStackChanged() {
        handleDisplayHomeUp();
    }

    /***
     * Will check back stack to properly display home as up
     * or hamburger icon for navigation drawer.
     *
     * @return true if there is a back stack or false if it's empty
     */
    public boolean handleDisplayHomeUp() {
        boolean hasBackStack = getSupportFragmentManager().getBackStackEntryCount() > 0;
        mDrawerToggle.setDrawerIndicatorEnabled(!hasBackStack);
        getSupportActionBar().setDisplayShowHomeEnabled(hasBackStack);
        return hasBackStack;
    }

    /**
     * Select a section in navigation drawer.
     * Transition to new fragment and close the navigation drawer.
     * @param position index of item in navigation drawer
     */
    private void selectItem(int position) {
        Fragment fragment;
        switch (position) {
            case ACTIVITY_SOCKET:
                fragment = new SocketGridFragment();
                break;
            case ACTIVITY_LIGHTING:
                fragment = new LightingListFragment();
                break;
            case ACTIVITY_CONVERSION:
                fragment = new ConversionFragment();
                break;
            case ACTIVITY_INFO:
                fragment = new InfoListFragment();
                break;
            default:
                fragment = new SocketGridFragment();
        }

        Bundle args = new Bundle();
        args.putInt(ACTIVITY_SERVICE, position);
        fragment.setArguments(args);

        FragmentManager fragmentManager = getSupportFragmentManager();
        fragmentManager.popBackStackImmediate(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
        fragmentManager.beginTransaction().replace(R.id.content_frame, fragment, FRAG_TAG).commit();
        // update title
        setTitle(FRAGMENT_TITLES[position]);
        // close drawer
        mDrawerLayout.closeDrawer(mDrawer);
    }

    @Override
    public void setTitle(CharSequence title) {
        mTitle = title;
        getSupportActionBar().setTitle(mTitle);
    }

    @Override
    public void onXmlClick(View view) {
        Fragment theFrag = getSupportFragmentManager().findFragmentByTag(FRAG_TAG);
        if (theFrag instanceof XmlClickable) {
            ((XmlClickable) theFrag).onXmlClick(view);
        } else {
            Log.e(TAG, "OnXmlClick: Frag was not XmlClickable: " + theFrag);
        }
    }

    @Override
    public void swapFragment(Fragment fragment, boolean addToBackStack) {
        FragmentTransaction fragTransaction = getSupportFragmentManager().beginTransaction();
        fragTransaction.replace(R.id.content_frame, fragment, FRAG_TAG);
        if (addToBackStack) {
            fragTransaction.addToBackStack(null);
        }
        fragTransaction.commit();
    }

    @Override
    public void setFragmentTitle(String title) {
        setTitle(title);
    }

    /**
     *  Navigation uses this as click listener
     */
    private class DrawerItemClickListener implements ListView.OnItemClickListener {

        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
            if (mActiveDrawerItem != null) {
                mActiveDrawerItem.setCompoundDrawablesWithIntrinsicBounds(DRAWER_ICONS[mActivePosition], 0, 0, 0);
            }
            ((CheckedTextView)view).setChecked(true);
            ((CheckedTextView) view).setCompoundDrawablesWithIntrinsicBounds(DRAWER_ICONS_SELECTED[position], 0, 0, 0);
            selectItem(position);

            mActiveDrawerItem = (CheckedTextView) view.findViewById(R.id.drawer_text);
            mActivePosition = position;
        }
    }

    /**
     * Responsible for populating navigation drawer with icons and titles
     */
    private class DrawerAdapter extends ArrayAdapter<String> {

        public DrawerAdapter(Context ctx) {
            super(ctx, R.layout.drawer_item, R.id.drawer_text);

            for (int i = 0, N = DRAWER_TITLES.length; i < N; i++) {
                add(getString(DRAWER_TITLES[i]));
            }
            notifyDataSetChanged();
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            // recycle
            View row = super.getView(position, convertView, parent);

            // inflate
            if (row == null) {
                LayoutInflater inflater = getLayoutInflater();
                row = inflater.inflate(R.layout.info_listitem, parent, false);
            }

            // icon
            CheckedTextView textView = (CheckedTextView) row.findViewById(R.id.drawer_text);
            int drawable = position == mActivePosition? DRAWER_ICONS_SELECTED[position] : DRAWER_ICONS[position];
            textView.setCompoundDrawablesWithIntrinsicBounds(drawable, 0, 0, 0);

            // handle first case
            if (mActivePosition == 0 && position == 0) {
                mActiveDrawerItem = textView;
            }
            return row;
        }
    }
}
